package org.outlook.crawler.util.xml;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.outlook.crawler.client.pojo.MetaData;
import org.outlook.crawler.util.Fetcher;
import org.outlook.crawler.util.xml.pojo.Rule;


public class XMLParser {
	
	public static List<MetaData> analyzeXML(InputStream is, Rule rule) throws XMLStreamException {
		String[] filters = rule.getFilters().split(",");
		boolean concate = rule.isConcate();
		String separator = rule.getSeparator();
		boolean positive = rule.isPositive();
		
		XMLInputFactory factory = XMLInputFactory.newInstance();
		factory.setProperty(XMLInputFactory.IS_COALESCING, true);
		XMLStreamReader r = factory.createXMLStreamReader(is);
		
		String key = null;
		String lastTag = null;
		List<MetaData> list = new ArrayList<MetaData>();
		
		try {
			int event = r.getEventType();
			while (true) {
				switch (event) {
				case XMLStreamConstants.START_DOCUMENT:
					break;
				case XMLStreamConstants.START_ELEMENT:
					key = r.getName().toString();
					for (int i = 0, n = r.getAttributeCount(); i < n; ++i) {
						if(positive) {
							String attributeName = r.getAttributeName(i).toString();
							if(isFilter(filters, attributeName)) {
								list.add(new MetaData(attributeName, r
										.getAttributeValue(i)));
							}
						} else {
							list.add(new MetaData(r.getAttributeName(i).toString(), r
									.getAttributeValue(i)));
						}
					}

					lastTag = r.getName().toString();

					break;
				case XMLStreamConstants.CHARACTERS:
					if (r.isWhiteSpace())
						break;

					boolean isFilter = isFilter(filters, key);
					if(positive) {
						if (isFilter) {
							if(concate && key.equalsIgnoreCase(lastTag)) {
								concatWithSeparator(list, r.getText(), separator);
							} else
								list.add(new MetaData(key, r.getText()));
						}
					} else {
						if (isFilter) {
							break;
						}
						
						if(concate && key.equalsIgnoreCase(lastTag)) {
							concatWithSeparator(list, r.getText(), separator);
						} else
							list.add(new MetaData(key, r.getText()));
					}

					break;
				case XMLStreamConstants.END_ELEMENT:
					break;
				case XMLStreamConstants.END_DOCUMENT:
					break;
				default :
					break;
				}

				if (!r.hasNext())
					break;

				event = r.next();
			}
		} finally {
			if (r != null) {
				r.close();
			}
		}
		
		return list;
	}

	private static boolean isFilter(String[] filters, String key) {
		boolean isFilter = false;
		for (String filter : filters) {
			if (key.indexOf(filter) >= 0) {
				isFilter = true;
				break;

			}
		}
		return isFilter;
	}
	
	static void concatWithSeparator(List<MetaData> list, String value, String separator) {
		int size = list.size();
		MetaData data = list.get(size - 1);
		data.setValue(data.getValue() + separator + value);
	}

	public static void main(String[] args) throws XMLStreamException {
		String requestUrl = "http://cc00.clearspring.com/imdb/Search?Both=Bolt";
		HttpURLConnection conn = null;
		InputStream is = Fetcher.getGetRequest(requestUrl, conn);
		Rule rule = new Rule();
		String filters = "TitleId";
		rule.setFilters(filters);
		rule.setPositive(true);
		List<MetaData> list = analyzeXML(is, rule);
		if(null != list)
			for(MetaData c : list) {
				System.out.println(c.getKey() + ":" + c.getValue());
			}
		if(is !=null)
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		if(conn != null)
			conn.disconnect();
	}

}